package net.hangar5.xmlrpc;

/* Dispatcher.java

The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.

The Original Code is "Hangar5 XMLRPC Library".

The Initial Developer of the Original Code is James D. Rudnicki.
Portions created by James D. Rudnicki are
Copyright (C) 2001.  All Rights Reserved.

Contributor(s):
*/
import java.util.*;
import java.io.*;

/**
 * Dispatcher takes the xml call as a StringBuffer, parses the call,
 * executes the appropriate method, and forms the response into a StringBuffer.
 *
 * It makes use of CallParser to take apart the XML, and RespWriter to
 * form the XML response.
 *
 */
public class Dispatcher extends java.lang.Object
{
  /**
   * Table of (method name, method object) pairs
   * All keys are instances of String.
   * All elements are instances of IMethod.
   */
  protected Hashtable tableMethods;

  /** Creates new Dispatcher */
  public Dispatcher()
  {
	tableMethods = new Hashtable();
  }
  /**
   * Add a method to the dispatchers table in global namespace.
   */
  public void addMethod( IMethod m )
  {
	tableMethods.put( m.getName(), m );
  }
  /**
   * Add a method to the dispatchers table in an objects namespace.
   */
  public void addMethod( IMethod m, String strUriObject )
  {
	String strFullName;
	strFullName = strUriObject +"/"+ m.getName();
	tableMethods.put( strFullName, m );
  }
  /**
   * Take the supplied StringBuffer and execute the call
   */
  public StringBuffer executePost( String strUriObject, StringBuffer sbCall ) throws IOException
  {
	StringBuffer sbResp;
	long l1, l2;
	sbResp = executeXml( strUriObject, sbCall );
	return sbResp;
  }
  /**
   * Take the supplied StringBuffer, and execute the call contained
   * within.  Return the fully formed XML response in a StringBuffer
   */
  public StringBuffer executeXml( String strUriObject, StringBuffer sbCall )
  {
	Object oRet = null;
	StringBuffer sbResp;
	try
        {
	  CallParser cp = new CallParser( sbCall );

	  if( cp.parseXml() )
          {
		String strFullName;
		if( 0 == strUriObject.compareTo("/") )
                {
		  strFullName = cp.getMethodName();
		}
		else
                {
		  strFullName = strUriObject.substring(1)+ "/" + cp.getMethodName();
		}
                IMethod m = (IMethod)tableMethods.get( strFullName );
                if (m != null)
                {
		  oRet = m.execute( cp.getParams() );
		}
		else
                {
		  throw new RpcException( RpcException.NOSUCHMETHOD, strFullName );
		}
	  }
	  else
          {
		oRet = null;
	  }

	  if( null == oRet )
          {
		throw new RpcException( RpcException.GENERIC, RpcException.SGENERIC );
	  }

	  sbResp = RespWriter.writeObject( oRet );
	}
	catch( RpcException x )
        {
	  sbResp = RespWriter.write( x );
	}
	return sbResp;
  }
  public Hashtable getMethodTable()
  {
	return tableMethods;
  }
  //public void setVerbose( boolean b )
  //{
  //}

  /**
   * Notify all methods of impending shutdown.
   */
  public void shutdown()
  {
	Enumeration e = tableMethods.elements();
	IMethod m;
	while( e.hasMoreElements() )
        {
	  m = (IMethod)e.nextElement();
	  m.shutdown();
	}
	return;
  }
} // end of class
